#ifndef PACKET_HPP
#define PACKET_HPP

// std-Header
#include <vector>
#include <map>
#include <string>

// SFML-Header
#include <SFML/Network.hpp>
#include <SFML/System.hpp>

namespace sf
{
	template<class T>
	sf::Packet& operator<<(sf::Packet& packet, std::vector<T>& t)
	{
		packet << t.size();
		for (int i = 0; i < t.size(); i++)
			packet << t[i];

		return packet;
	}

	template<class T>
	sf::Packet& operator>>(sf::Packet& packet, std::vector<T>& t)
	{
		unsigned int size;
		packet >> size;
		t.reserve(size);
		for (int i = 0; i < size; i++)
		{
			T temp;
			packet >> temp;
			t.push_back(temp);
		}
		return packet;
	}

	template<class T>
	sf::Packet& operator+(sf::Packet& packet, std::vector<T>& t)
	{
		return packet << t;
	}

	template<class T>
	sf::Packet& operator-(sf::Packet& packet, std::vector<T>& t)
	{
		return packet >> t;
	}

	template<class N, class T>
	sf::Packet& operator<<(sf::Packet& packet, std::map<N, T>& t)
	{
		packet << t.size();
		for (std::map<N, T>::const_iterator iter = t.begin(); iter != t.end(); iter++)
			packet << iter->first << iter->second;

		return packet;
	}

	template<class N, class T>
	sf::Packet& operator>>(sf::Packet& packet, std::map<N, T>& t)
	{
		unsigned int size;
		packet >> size;
		for (unsigned int i = 0; i < size; i++)
		{
			N tempn;
			T tempt;
			packet >> tempn << tempt;
			t.insert(std::make_pair<N, T>(tempn, tempt));
		}
		return packet;
	}

	template<class N, class T>
	sf::Packet& operator+(sf::Packet& packet, std::map<N, T>& t)
	{
		return packet << t;
	}

	template<class N, class T>
	sf::Packet& operator-(sf::Packet& packet, std::map<N, T>& t)
	{
		return packet >> t;
	}

	template<class T>
	sf::Packet& operator<<(sf::Packet& packet, sf::Vector2<T>& p)
	{
		return packet << p.x << p.y;
	}

	template<class T>
	sf::Packet& operator>>(sf::Packet& packet, sf::Vector2<T>& p)
	{
		return packet >> p.x >> p.x;
	}

	template<class T>
	sf::Packet& operator+(sf::Packet& packet, sf::Vector2<T>& p)
	{
		return packet << p;
	}

	template<class T>
	sf::Packet& operator-(sf::Packet& packet, sf::Vector2<T>& p)
	{
		return packet >> p;
	}

	template<class T>
	sf::Packet& operator<<(sf::Packet& packet, sf::Vector3<T>& p)
	{
		return packet << p.x << p.y << p.z;
	}

	template<class T>
	sf::Packet& operator>>(sf::Packet& packet, sf::Vector3<T>& p)
	{
		return packet >> p.x >> p.x >> p.z;
	}

	template<class T>
	sf::Packet& operator+(sf::Packet& packet, sf::Vector3<T>& p)
	{
		return packet << p;
	}

	template<class T>
	sf::Packet& operator-(sf::Packet& packet, sf::Vector3<T>& p)
	{
		return packet >> p;
	}
}

#endif //PACKET_HPP